#include "../include.h"

#include "rand.h"

TEST_CASE("Test Random", "[rand]") {
  using namespace afcore;

  printf("%u\n", CRandom::Instance().Rand32());
  printf("%d\n", CRandom::Instance().RandI32());
  printf("%u\n", CRandom::Instance().RandU32());
  printf("%f\n", CRandom::Instance().RandFloat());
  printf("%f\n", CRandom::Instance().RandDouble());
  printf("%u\n", CRandom::Instance().RandMS());
  printf("%u\n", CRandom::Instance().RandTime(RMilliseconds(300), RMilliseconds(500)));
  printf("%f\n", CRandom::Instance().RandChance());
  printf("%d\n", CRandom::Instance().RollChanceFloat(80.6));
  printf("%d\n", CRandom::Instance().RollChanceI32(30));
}

TEST_CASE("Test Random Weighted", "[rand]") {
  const int kThousand10 = 10000;
  const int kThousand100 = 100000;

  using namespace afcore;

  std::vector<double> weights {1000.0, 1500.0, 2000.0, 1500.0, 4000.0, 3000.0};
  std::map<uint32_t, uint32_t> result_map;

  size_t count = weights.size();

  // 10000次
  for (int i = 0; i < kThousand10; ++i) {
    ++result_map[CRandom::Instance().RandU32Weighted(count, weights.data())];
  }

  printf("\n");
  for (auto&& itr : result_map) {
    printf("%u - %8u\t%s\n", itr.first, itr.second, std::string(static_cast<int>(itr.second * 100.0 / kThousand10), '*').c_str());
  }

  result_map.clear();
  // 100000次
  for (int i = 0; i < kThousand100; ++i) {
    ++result_map[CRandom::Instance().RandU32Weighted(count, weights.data())];
  }

  printf("\n");
  for (auto&& itr : result_map) {
    printf("%u - %8u\t%s\n", itr.first, itr.second, std::string(static_cast<int>(itr.second * 100.0 / kThousand100), '*').c_str());
  }
}

std::mutex random_mutex;

void Rand32InMutithread(const int thread_id) {
  using namespace afcore;
  std::vector<uint32_t> results;

  for (int i = 0; i < 5; ++i) {  
    results.emplace_back(CRandom::Instance().Rand32());
  }
  std::lock_guard<std::mutex> lock(random_mutex);
  for (auto&& ret : results) {
    std::cout << "thread_id:" << thread_id << " -- " << ret << std::endl;
  }
  std::cout << std::endl;
}

TEST_CASE("Test Random MutiThread", "[rand]") {
  std::cout << std::endl;
  std::vector<std::thread> Threads;

  for (int i = 1; i <= 4; ++i ) {
    Threads.emplace_back(std::thread(Rand32InMutithread, i));
  }

  for (auto&& t : Threads) {
    t.join();
  }
}